home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / convrtrs / hgrpic / a2b.c next >
C/C++ Source or Header  |  1991-05-02  |  9KB  |  336 lines

  1. /*
  2.  * A2B.C -- Program to convert Apple// Hi-Res Screen Dumps to
  3.  *          320x200x4 .PIC format IBM graphics files.  The result is an
  4.  *          IBM memory map (i.e., a BASIC BLOAD picture).
  5.  *
  6.  *          Program assumes that the input file is an uncompressed
  7.  *          280x192 color picture (Apple// HGR memory BSAVE) that
  8.  *          has already been ported to the IBM environment.
  9.  *
  10.  * Usage:   a2i <applefile> [WAIT]
  11.  *
  12.  *          If no extension is given, an extension of .RAW is assumed.
  13.  *          Output file generated uses same name as input file, with
  14.  *          a .PIC extension.
  15.  *
  16.  *          If you add "WAIT" to the command line (or anything really,
  17.  *          as all I check for is a 2nd parameter) the program will beep
  18.  *          and wait for a keypress before exiting.  Leaving this off the
  19.  *          command line makes the program work from a batch file for
  20.  *          multiple conversions.
  21.  */
  22.  
  23. /* INCLUDES */
  24.  
  25. #include <stdio.h>
  26. #include <process.h>
  27. #include <dir.h>
  28. #include <conio.h>
  29. #include <dos.h>
  30.  
  31. #include "cga.h"
  32.  
  33.  
  34.  
  35.  
  36. /* DEFINES */
  37.  
  38. #define ERROR -1
  39. #define A_OK   0
  40.  
  41. /*
  42.  * The following are the color equivalents in the CGA pallette that
  43.  * closely (relatively) approximate the Apple screen colors.  This
  44.  * program example thinks in the cyan/magenta/white pallette, but can
  45.  * easily be adapted to the green/red/yellow.
  46.  */
  47.  
  48. #define _A_BLACK   0
  49.  
  50. #define _A_VIOLET  _RED
  51. #define _A_GREEN   _BLUE
  52. #define _A_BLUE    _BLUE
  53. #define _A_ORANGE  _RED
  54. #define _A_WHITE   _WHITE
  55.  
  56.  
  57.  
  58.  
  59. /* GLOBALS */
  60.  
  61. UBYTE apple_memory[192][40];        /* Apple "memory" map */
  62.  
  63. int apple_lines[8][3] = {
  64.              {  0,  64, 128 },
  65.              {  8,  72, 136 },
  66.              { 16,  80, 144 },
  67.              { 24,  88, 152 },
  68.              { 32,  96, 160 },
  69.              { 40, 104, 168 },
  70.              { 48, 112, 176 },
  71.              { 56, 120, 184 }
  72.             };        /* Index table for Apple memory */
  73.  
  74. /*
  75.  * The Apple HGR screen is wonderfully convoluted (in several ways).  For
  76.  * instance, the color of a particular pixel on the Apple screen depends
  77.  * upon THREE (3) things:
  78.  *
  79.  *   1) Is the Apple screen byte an EVEN or ODD byte on the scanline?
  80.  *   2) Is the MSB of the screen byte SET?
  81.  *   3) Is the pixel/bit in question on an EVEN or ODD column?
  82.  *
  83.  * Pretty confusing, huh?  a2i_colors[][][] handles this as follows:
  84.  *
  85.  *   Pixel_color = a2i_colors[EVEN/ODD byte?][MSB SET?][EVEN/ODD column?]
  86.  */
  87.  
  88. int a2i_colors[2][2][2] = {
  89.                { /* EVEN byte        */
  90.                 { _A_VIOLET, _A_GREEN  },    /* MSB not set */
  91.                 { _A_BLUE  , _A_ORANGE }    /* MSB set     */
  92.                },
  93.                { /* ODD byte         */
  94.                 { _A_GREEN , _A_VIOLET },   /* MSB not set */
  95.                 { _A_ORANGE, _A_BLUE   }    /* MSB set     */
  96.                }
  97.               };
  98.  
  99.  
  100.  
  101.  
  102. /* FUNCTIONS */
  103.  
  104. /*
  105.  * load_apple_raw() -- Take a raw BSAVE file and load it into the temporary
  106.  *                     memory buffer.  This routine unscrambles Apple's
  107.  *                     memory mapping at the same time, so that the buffer
  108.  *                     becomes consecutive, as opposed to Apple's convoluted
  109.  *                     skipping from block to block.
  110.  */
  111. int load_apple_raw(const char *fname)
  112. {
  113.  int  i, vline, block, mline = 0;
  114.  FILE *fsave;
  115.  
  116.  
  117.  if((fsave = fopen(fname, "rb")) == NULL)
  118.   return ERROR;
  119.  
  120.  rewind(fsave);
  121.  
  122.  /*
  123.   * Even though we're dealing with Apple graphics, the screen map is still
  124.   * heavily tied to the text screen layout.  Apple's HGR screen is divided
  125.   * into 24 "blocks" of 8 lines per block (the main reason why when you do
  126.   * a BLOAD to the HGR screen, you get the infamous "venetian blind" load.
  127.   * Unfortunately, we end up stepping through memory (scanline-wise) as
  128.   * follows:
  129.   *
  130.   *   0, 64, 128, 8, 72, 136, ..., 184, 1, 65, 129, ...
  131.   *
  132.   * (i.e. line 0 is the first line of the file, line 1 is the 25th line of
  133.   * the file...wonderful, right?)
  134.   *
  135.   * If that isn't enough, every there are an additional 8 bytes of garbage
  136.   * space every 3 scanlines (reminiscent of IBM's CGA architecture).
  137.   *
  138.   * The easiest way I found to handle this is to create the apple_lines[][]
  139.   * table of base scanlines and index off of them.
  140.   */
  141.  
  142.  for(block=0;block<8;block++) 
  143.   for(mline=0;mline<24;mline++)
  144.    {
  145.    vline = apple_lines[mline / 3][mline % 3] + block;
  146.  
  147.    for(i=0;i<40;i++)
  148.     apple_memory[vline][i] = fgetc(fsave);
  149.  
  150.    if((mline % 3) == 2)
  151.     for(i=0;i<8;i++)
  152.      fgetc(fsave);
  153.    }
  154.  
  155.  fclose(fsave);
  156.  
  157.  return A_OK;
  158. }
  159.  
  160.  
  161.  
  162. /*
  163.  * apple_2_ibm() -- Take the "Apple map" image in the apple_memory[][]
  164.  *                  array and translate it into an CGA mode 4 image on
  165.  *                  the display.  xoff and yoff are pixel offsets on the
  166.  *                  CGA screen that result in the Apple image (280x192)
  167.  *                  being displayed dead center on the CGA screen (320x200).
  168.  */
  169. void apple_2_ibm(void)
  170. {
  171.  int   xoff = 20, yoff = 4;
  172.  int   i, j, k, which, line[280];
  173.  UBYTE abyte, abit;
  174.  
  175.  
  176.  for(i=0;i<192;i++)               /* 192 lines in an Apple HGR screen */
  177.   {
  178.  
  179.   /*
  180.    * The first thing we do is convert an Apple scanline to a CGA scanline,
  181.    * meaning that we must decode each Apple byte (7 pixels per byte) into
  182.    * CGA pixels.  line[] is the line buffer, each index holding one pixel's
  183.    * color value.
  184.    */
  185.  
  186.   for(j=0;j<40;j++)                    /* 280 pixels/line = 40 Apple bytes */
  187.    {
  188.    abyte = apple_memory[i][j];           /* Get an Apple byte                */
  189.  
  190.    which = (abyte & 0x80) == 0x80;     /* Which Apple color scheme?        */
  191.  
  192.    /*
  193.     * Now, cycle through the Apple byte one pixel at a time.  Since Apple
  194.     * bytes are encoded "backwards" to IBM screenlines, the least significant
  195.     * bit of the Apple byte is the far right pixel of the IBM byte.
  196.     * Therefore, the decompression process works as follows:
  197.     *
  198.     *   1) Grab LSB of Apple byte.
  199.     *   2) Set equivalent EGA pixel to correct Apple color (remember, Apple
  200.     *      colors depend upon:  A) whether the pixel is in an even or odd
  201.     *      column (on the Apple screen), and B) whether the high bit of the
  202.     *      Apple byte is set or not.
  203.     *   3) Shift Apple byte right one bit.
  204.     *   4) Repeat steps 1-3 for remaining 6 pixels in Apple byte
  205.     */
  206.  
  207.    for(k=0;k<7;k++)               /* 7 pixels per Apple byte          */
  208.     {
  209.     abit = abyte & 0x01;
  210.  
  211.     line[j*7 + k] = a2i_colors[j % 2][which][k % 2] * abit;
  212.  
  213.     abyte >>= 1;
  214.     }
  215.    }
  216.  
  217.   /*
  218.    * Now that we've built a CGA screen line, write it out to screen memory.
  219.    * The actual color displayed on the Apple screen depends not only on
  220.    * whether a given pixel is set or not, but also on whether adjacent
  221.    * pixels are set (if two adjacent pixels are on, the resulting color is
  222.    * WHITE, *not* the individual pixel colors).  The algorithm is:
  223.    *
  224.    *   IF (current pixel first on scanline)
  225.    *     Check the next pixel
  226.    *     IF (both pixels aren't black)
  227.    *       Write out a white pixel
  228.    *     ELSE
  229.    *       Write out the color of the first pixel
  230.    *   ELSE IF (current pixel last on scanline)
  231.    *     Check the previous pixel
  232.    *     IF (both pixels aren't black)
  233.    *       Write out white pixel
  234.    *     ELSE
  235.    *       Write out the color of the last pixel
  236.    *   ELSE
  237.    *     IF (current pixel not black) AND (previous OR next pixel not black)
  238.    *       Write out a white pixel
  239.    *     ELSE IF (current pixel black) AND (previous pixel same color as
  240.    *                                        next pixel)
  241.    *       Write out color of previous pixel
  242.    *     ELSE
  243.    *       Write out color of current pixel
  244.    *
  245.    * The convoluted part of the algorithm (the last part of the main IF
  246.    * structure) is because 2 ON pixels with 1 OFF pixel between them on
  247.    * the Apple screen are seen as a solid color (no gaps).
  248.    */
  249.  
  250.   for(k=0;k<280;k++)
  251.    {
  252.    if(k == 0)
  253.     {
  254.     if(line[k]!=_A_BLACK && line[k+1]!=_A_BLACK)
  255.      put_pixel(k + xoff, i + yoff, _A_WHITE);
  256.     else
  257.      put_pixel(k + xoff, i + yoff, line[k] );
  258.     }
  259.    else
  260.    if(k == 279)
  261.     {
  262.     if(line[k]!=_A_BLACK && line[k-1]!=_A_BLACK)
  263.      put_pixel(k + xoff, i + yoff, _A_WHITE);
  264.     else
  265.      put_pixel(k + xoff, i + yoff, line[k] );
  266.     }
  267.    else
  268.     {
  269.     if(line[k]!=_A_BLACK && (line[k-1]!=_A_BLACK || line[k+1]!=_A_BLACK))
  270.      put_pixel(k + xoff, i + yoff, _A_WHITE );
  271.     else
  272.     if(line[k]==_A_BLACK && line[k-1]==line[k+1])
  273.      put_pixel(k + xoff, i + yoff, line[k-1]);
  274.     else
  275.      put_pixel(k + xoff, i + yoff, line[k]  );
  276.     }
  277.    }
  278.   }
  279. }
  280.  
  281.  
  282.  
  283.  
  284. /* MAIN */
  285.  
  286. void main(int argc, char **argv)
  287. {
  288.  char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  289.  char infile[13], outfile[13];
  290.  
  291.  
  292.  if(argc == 1)
  293.   {
  294.   printf("Usage:  a2b <applefile> [WAIT]\n");
  295.   exit(0);
  296.   }
  297.  
  298.  init_cgfx(0x04);            /* Initialize CGA mode 4 */
  299.  fnsplit(argv[1], drive, dir, file, ext);
  300.  
  301.  if(ext[0] == '\0')
  302.   fnmerge(infile, "", "", file, ".RAW");
  303.  else
  304.   fnmerge(infile, "", "", file, ext   );
  305.  
  306.  fnmerge(outfile, "", "", file, ".PIC");
  307.  
  308.  gotoxy(12, 10);  printf("Loading...");
  309.  
  310.  if(load_apple_raw(infile) != ERROR)
  311.   {
  312.   gotoxy(12, 10);  printf("Converting...");
  313.  
  314.   apple_2_ibm();
  315.  
  316.   sleep(2);
  317.  
  318.   save_pic(outfile);
  319.  
  320.   cls();
  321.  
  322.   fload_pic(outfile);
  323.  
  324.   if(argc == 3)
  325.    {
  326.    putch(7);  
  327.  
  328.    getch();
  329.    }
  330.   }
  331.  else
  332.   printf("Error...");
  333.  
  334.  mode(3);
  335. }
  336.